'use strict';
let dayjs = require("dayjs")
class BaseController {
    constructor(model) {
        this.model = model
    }

    /**
     * 更新数据
     * @param condition
     * @param updateData
     * @returns {Promise<unknown>}
     */
    async updateData(condition, updateData, incData = {}) {
        updateData.updateTime = updateData.updateTime || dayjs().format("YYYY-MM-DD HH:mm:ss")
        try {
            // 查找更新id是否存在
            let data = await this.model.findOne(condition)
            if (!data)
                throw new Error("未找到更新数据,请检查id是否有误")
            
            // 更新数据
            let result = await this.model.updateOne(condition, {
                $set: updateData,
                $inc: incData
            })
            
            if (result.modifiedCount != 0)
                return result
            throw result
        } catch (error) {
            throw error
        }
    }
    
    /**
     * 添加数据
     * @param data
     * @returns {Promise<unknown>}
     */
    async addData(data) {
        data.createTime = data.createTime || dayjs().format("YYYY-MM-DD HH:mm:ss")
        try {
            let model = new this.model(data)
            await model.save()
            return model
        } catch (error) {
            let err = error.errors
            let msg = ""
            if (err) {
                for (let key in err) {
                    msg += err[key].message + ", "
                }
            }
            if (msg != "") msg = msg.slice(0, msg.length - 2)
            throw new Error(msg)
        }
    }

    /**
     * 删除数据,成功则返回删除的数据,不成功则返回查找条件
     * @param condition
     * @returns {Promise<unknown>}
     */
    async removeData(condition) {
        try {
            // 查找更新id是否存在
            let data = await this.model.findOne(condition)
            if (!data) {
                throw new Error("未找到数据,请检查id是否有误")
            }
            
            let result = await this.model.findOneAndDelete(condition)
            if (result)
                return result
            else throw condition
        } catch (error) {
            throw error
        }
    }

    /**
     *  根据id获取数据
     * @param condition
     * @param projection
     * @returns {Promise<unknown>}
     */
    async getData(condition, projection) {
        try {
            const model = await this.model.findOne(condition, projection || {})
            if (!model) { // 数据不存在
                throw condition
            }
            return model
        } catch (error) {
            throw error
        }
    }

    /**
     * 验证必填参数,都符合则返回空字符串
     * @param data
     * @param params
     * @returns {string}
     */
    verifyData(data, params) {
        let r = ""
        if (!params || !params.length || params.length == 0) {
            console.log("params不符合要求")
            return r
        }
        for (let i = 0; i < params.length; i++) {
            let param = params[i]
            if (data[param] == undefined || data[param].toString().trim() == "") {
                r += param + ","
            }
        }
        if (r.length > 0) r = r.slice(0, r.length - 1)
        return r
    }
    
    //#region 分页
    /**
     * 查询分页数据
     * @param node_model 对象
     * @param conditions find条件
     * @param options 分页设置
     * @param res
     * @param parser 数据处理函数
     */
    async getListByPage(node_model, conditions, projection, options) {
        try {
            let total = await this.getTotal(node_model, conditions, projection)
            let data = await this.where(node_model, conditions, projection, options)
            return { data: data, total: total }
        } catch (err) {
            throw err
        }
    }
    
    /**
     * 根据条件获取有多少条数据 文档数
     * @param node_model 表名
     * @param conditions 查询条件 {a:1, b:2}
     */
    async getTotal(node_model, conditions, projection) {
        try {
            return await node_model.find(conditions, projection).countDocuments()
        } catch (err) {
            throw err
        }
    }

    /**
     * 连写查询 查询多条数据
     * @param node_model 表名
     * @param conditions 查询条件 {a:1, b:2}
     * @param options 选项：{fields: "a b c", sort: {time: -1}, limit: 10}
     */
    async where(node_model, conditions, projection, options) {
        try {
            let query = node_model.find(conditions, projection)
            
            if (options.fields) {
                query = query.select(options.fields)
            }
            
            if (options.sort) {
                query = query.sort(options.sort)
            }
            
            if (options.skip) {
                query = query.skip(options.skip)
            }
            
            if (options.limit) {
                query = query.limit(options.limit)
            }
            
            return await query
        } catch (err) {
            throw err
        }
    }

    //#endregion
    /**
     * 默认查询条件
     * @param data
     * @returns {{id: *}}
     */
    getCondition(data) {
        return { id: data.id }
    }

    //#region 覆写函数
    /**
     * 解析数据处理
     * @param req
     * @returns {*}
     */
    parseData(req) {
        if (req.body.data)
            return req.body.data
        return req.body
    }

    /**
     * 获取分页数据之后的处理
     * @param list
     */
    async parseList(list) { }

    /**
     * 获取单个数据之后的处理
     * @param item
     */
    async parseItem(item) { }
    //#endregion
    
    //#region 预处理
    /**
     * 添加操作之前的处理
     * @param {} data 
     */
    async beforeAdd(data) {

    }
    /**
     * 添加操作之后的处理
     * @param {} data
     */
    async afterAdd(data) {

    }
    /**
     * 更新操作之前的处理
     * @param {*} data 
     */
    async beforeUpdate(data) {

    }
    /**
     * 更新操作之后的处理
     * @param {*} data
     */
    async afterUpdate(updateData, r) {

    }
    /**
    * 删除操作之前的处理
    * @param {*} data 
    */
    async beforeDelete(data) {

    }
    /**
     * 删除操作之后的处理
     * @param {*} data
     */
    async afterDelete(data) {

    }
    /**
    * 搜索操作之前的处理
    * @param {*} data 
    */
    async beforeSearch(data) {

    }
    /**
     * 搜索操作之后的处理
     * @param {*} data
     */
    async afterSearch(data) {

    }
    /**
     * 获取操作之前的处理
     * @param {*} data 
     */
    async beforeGet(data) {

    }
    /**
     * 获取操作之后的处理
     * @param {*} data
     */
    async afterGet(data) {

    }
    //#endregion
    
    //#region log
    logAction() {

    }
    //#endregion
}

module.exports = BaseController